TOOL_CHAIN_PATH ?= /opt/gcc-riscv/riscv-wch-embedded-gcc-v1.70/bin
OPENOCD_PATH    ?= /opt/openocd/wch-openocd-v1.70/bin
PROJECT_NAME    = ch32v208wbu6_liteos

#启动汇编文件
TOP_DIR     := .
OUTPUT_DIR  := $(TOP_DIR)/Build
STARTUP_DIR := $(TOP_DIR)/Startup
RISC_S_DIR := $(TOP_DIR)/LiteOS/kernel/arch/risc-v/V4A/gcc

#C文件
CORE_DIR    := $(TOP_DIR)/Core
DEBUG_DIR   := $(TOP_DIR)/Debug
SPL_DIR     := $(TOP_DIR)/Peripheral
USER_DIR    := $(TOP_DIR)/User
USER_DRIVER_DIR    :=  $(TOP_DIR)/UserDriver
RTOS_DIR    :=  $(TOP_DIR)/LiteOS/kernel/src
RTOS_PORT_DIR    :=  $(TOP_DIR)/LiteOS/kernel/arch/risc-v/V4A/gcc
RTOS_MM_DIR    :=  $(TOP_DIR)/LiteOS/kernel/src/mm
RTOS_DB_DIR    :=  $(TOP_DIR)/LiteOS/utils
RTOS_PW_DIR    :=  $(TOP_DIR)/LiteOS/components/power
RTOS_BT_DIR    :=  $(TOP_DIR)/LiteOS/components/backtrace
RTOS_CP_DIR    :=  $(TOP_DIR)/LiteOS/components/cpup
RTOS_TP_DIR    :=  $(TOP_DIR)/LiteOS/third_party/bounds_checking_function/src

#头文件
INCLUDES := $(INCLUDES)
INCLUDES += -IUser
INCLUDES += -ICore
INCLUDES += -IDebug
INCLUDES += -IPeripheral/inc
INCLUDES += -ILiteOS/kernel/include
INCLUDES += -ILiteOS/kernel/arch/include
INCLUDES += -ILiteOS/kernel/arch/risc-v/V4A/gcc
INCLUDES += -ILiteOS/utils
INCLUDES += -ILiteOS/utils/internal
INCLUDES += -ILiteOS/components/power
INCLUDES += -ILiteOS/components/backtrace
INCLUDES += -ILiteOS/components/cpup
INCLUDES += -ILiteOS/third_party/bounds_checking_function/include
INCLUDES += -IUserDriver

LD_FILE     := $(TOP_DIR)/Ld/Link.ld
OPENOCD_FILE := $(OPENOCD_PATH)/wch-riscv.cfg
MAP_FILE    := $(OUTPUT_DIR)/$(PROJECT_NAME).map
ELF_FILE    := $(OUTPUT_DIR)/$(PROJECT_NAME).elf
HEX_FILE    := $(OUTPUT_DIR)/$(PROJECT_NAME).hex
LST_FILE    := $(OUTPUT_DIR)/$(PROJECT_NAME).lst
SIZ_FILE    := $(OUTPUT_DIR)/$(PROJECT_NAME).siz

CCFLAGS := \
-march=rv32imac -mabi=ilp32 -msmall-data-limit=8 -msave-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common -Wunused  -g 
all: $(HEX_FILE) $(LST_FILE) $(SIZ_FILE)

STARTUP_SRCS := $(wildcard $(STARTUP_DIR)/*.S)
STARTUP_OBJS := $(patsubst $(STARTUP_DIR)/%.S, $(OUTPUT_DIR)/startup/%.o, $(STARTUP_SRCS)) # patsubst: in #3 replace #1 to #2

RISC_S_SRCS := $(wildcard $(RISC_S_DIR)/*.S)
RISC_S_OBJS := $(patsubst $(RISC_S_DIR)/%.S, $(OUTPUT_DIR)/risc_s/%.o, $(RISC_S_SRCS)) # patsubst: in #3 replace #1 to #2


CORE_SRCS := $(wildcard $(CORE_DIR)/*.c)
CORE_OBJS := $(patsubst $(CORE_DIR)/%.c, $(OUTPUT_DIR)/core/%.o, $(CORE_SRCS))

DEBUG_SRCS := $(wildcard $(DEBUG_DIR)/*.c)
DEBUG_OBJS := $(patsubst $(DEBUG_DIR)/%.c, $(OUTPUT_DIR)/debug/%.o, $(DEBUG_SRCS))

SPL_SRCS := $(wildcard $(SPL_DIR)/src/*.c)
SPL_OBJS := $(patsubst $(SPL_DIR)/src/%.c, $(OUTPUT_DIR)/spl/%.o, $(SPL_SRCS))

USER_SRCS := $(wildcard $(USER_DIR)/*.c)
USER_OBJS := $(patsubst $(USER_DIR)/%.c, $(OUTPUT_DIR)/user/%.o, $(USER_SRCS))

USER_DRIVER_SRCS := $(wildcard $(USER_DRIVER_DIR)/*.c)
USER_DRIVER_OBJS := $(patsubst $(USER_DRIVER_DIR)/%.c, $(OUTPUT_DIR)/user_driver/%.o, $(USER_DRIVER_SRCS))

RTOS_SRCS := $(wildcard $(RTOS_DIR)/*.c)
RTOS_OBJS := $(patsubst $(RTOS_DIR)/%.c, $(OUTPUT_DIR)/rtos/%.o, $(RTOS_SRCS))

RTOS_PORT_SRCS := $(wildcard $(RTOS_PORT_DIR)/*.c)
RTOS_PORT_OBJS := $(patsubst $(RTOS_PORT_DIR)/%.c, $(OUTPUT_DIR)/rtos_port/%.o, $(RTOS_PORT_SRCS))

RTOS_MM_SRCS := $(wildcard $(RTOS_MM_DIR)/*.c)
RTOS_MM_OBJS := $(patsubst $(RTOS_MM_DIR)/%.c, $(OUTPUT_DIR)/rtos_mm/%.o, $(RTOS_MM_SRCS))

RTOS_DB_SRCS := $(wildcard $(RTOS_DB_DIR)/*.c)
RTOS_DB_OBJS := $(patsubst $(RTOS_DB_DIR)/%.c, $(OUTPUT_DIR)/rtos_db/%.o, $(RTOS_DB_SRCS))

RTOS_BT_SRCS := $(wildcard $(RTOS_BT_DIR)/*.c)
RTOS_BT_OBJS := $(patsubst $(RTOS_BT_DIR)/%.c, $(OUTPUT_DIR)/rtos_bt/%.o, $(RTOS_BT_SRCS))

RTOS_CP_SRCS := $(wildcard $(RTOS_CP_DIR)/*.c)
RTOS_CP_OBJS := $(patsubst $(RTOS_CP_DIR)/%.c, $(OUTPUT_DIR)/rtos_cp/%.o, $(RTOS_CP_SRCS))

RTOS_PW_SRCS := $(wildcard $(RTOS_PW_DIR)/*.c)
RTOS_PW_OBJS := $(patsubst $(RTOS_PW_DIR)/%.c, $(OUTPUT_DIR)/rtos_pw/%.o, $(RTOS_PW_SRCS))

RTOS_TP_SRCS := $(wildcard $(RTOS_TP_DIR)/*.c)
RTOS_TP_OBJS := $(patsubst $(RTOS_TP_DIR)/%.c, $(OUTPUT_DIR)/rtos_tp/%.o, $(RTOS_TP_SRCS))

$(OUTPUT_DIR)/startup/%.o: $(STARTUP_DIR)/%.S
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) -x assembler -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/risc_s/%.o: $(RISC_S_DIR)/%.S 
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -x assembler-with-cpp -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/core/%.o: $(CORE_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/debug/%.o: $(DEBUG_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/spl/%.o: $(SPL_DIR)/src/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/user/%.o: $(USER_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/user_driver/%.o: $(USER_DRIVER_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos/%.o: $(RTOS_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos_port/%.o: $(RTOS_PORT_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos_mm/%.o: $(RTOS_MM_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos_db/%.o: $(RTOS_DB_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos_pw/%.o: $(RTOS_PW_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos_bt/%.o: $(RTOS_BT_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos_cp/%.o: $(RTOS_CP_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(OUTPUT_DIR)/rtos_tp/%.o: $(RTOS_TP_DIR)/%.c
	@mkdir -p $(@D)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) $(INCLUDES) -std=gnu99 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"

$(ELF_FILE): $(STARTUP_OBJS) $(RISC_S_OBJS) $(CORE_OBJS) $(DEBUG_OBJS) $(SPL_OBJS)$(USER_OBJS) $(USER_DRIVER_OBJS) $(RTOS_OBJS) $(RTOS_PORT_OBJS)$(RTOS_MM_OBJS) $(RTOS_DB_OBJS)$(RTOS_PW_OBJS)$(RTOS_TP_OBJS)$(RTOS_BT_OBJS)$(RTOS_CP_OBJS)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-gcc $(CCFLAGS) -T $(LD_FILE) -nostartfiles -Xlinker --gc-sections -Wl,-Map,$(MAP_FILE) --specs=nano.specs --specs=nosys.specs -o $(ELF_FILE) $(USER_OBJS) $(STARTUP_OBJS)$(DEBUG_OBJS)$(CORE_OBJS)$(SPL_OBJS)$(RTOS_OBJS) $(RTOS_PORT_OBJS)\
	$(RTOS_MM_OBJS)$(RISC_S_OBJS)$(RTOS_DB_OBJS)$(RTOS_PW_OBJS)$(RTOS_TP_OBJS)$(RTOS_BT_OBJS)$(RTOS_CP_OBJS)$(USER_DRIVER_OBJS) 

$(HEX_FILE): $(ELF_FILE)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-objcopy -O ihex $(ELF_FILE) $(HEX_FILE)

$(LST_FILE): $(ELF_FILE)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-objdump --all-headers --demangle --disassemble $(ELF_FILE) > $(LST_FILE)

$(SIZ_FILE): $(ELF_FILE)
	$(TOOL_CHAIN_PATH)/riscv-none-embed-size --format=berkeley $(ELF_FILE)


.PHONY: clean
clean:
	rm -f $(OUTPUT_DIR)/startup/*
	rm -f $(OUTPUT_DIR)/risc_s/*
	rm -f $(OUTPUT_DIR)/core/*
	rm -f $(OUTPUT_DIR)/debug/*
	rm -f $(OUTPUT_DIR)/spl/*
	rm -f $(OUTPUT_DIR)/user/*
	rm -f $(OUTPUT_DIR)/user_driver/*
	rm -f $(OUTPUT_DIR)/rtos/*
	rm -f $(OUTPUT_DIR)/rtos_port/*
	rm -f $(OUTPUT_DIR)/rtos_mm/*
	rm -f $(OUTPUT_DIR)/rtos_db/*
	rm -f $(OUTPUT_DIR)/rtos_bt/*
	rm -f $(OUTPUT_DIR)/rtos_pw/*
	rm -f $(OUTPUT_DIR)/rtos_tp/*
	rm -f $(OUTPUT_DIR)/rtos_cp/*
	rm -f $(OUTPUT_DIR)/*.*

flash:
	$(OPENOCD_PATH)/openocd -f $(OPENOCD_FILE) -c init -c halt -c "flash erase_sector wch_riscv 0 last " -c "program $(ELF_FILE)" -c "verify_image $(ELF_FILE)" -c wlink_reset_resume -c exit

reset:
	$(OPENOCD_PATH)/openocd -f $(OPENOCD_FILE) -c init -c halt -c wlink_reset_resume -c exit

